using System;
using System.Collections.Generic;
using System.Text;

using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace LoggingServer
{
    public class LOGServer
    {
        public void Start()
        {
            IPAddress ip = IPAddress.Any;

            int port = 9082;
            try
            {
                port = int.Parse(
                    System.Configuration.ConfigurationManager.AppSettings["Port"].ToString());
                
            }
            catch (Exception ex)
            {
                port = 9082;
                StaticComponent.LogEx(ex);
            }


            TcpListener tcpListener = new TcpListener(ip, port);

            tcpListener.Start();

            Console.WriteLine("==============================");
            Console.WriteLine("Logging Server Starting");
            Console.WriteLine(string.Format("[Port]: {0}", port));
            Console.WriteLine("Waiting for connection....");

            while (true)
            {
                TcpClient tcpClient = tcpListener.AcceptTcpClient();

                Console.WriteLine("Client connected");

                NetworkStream ns = tcpClient.GetStream();
                new LogThread(ns);
            }
        }
    }

    class LogThread
    {
        NetworkStream ns;

        byte[] incoming = new byte[1024];

        public LogThread(NetworkStream _ns)
        {
            ns = _ns;

            new Thread(new ThreadStart(Run)).Start();
        }

        public void Run()
        {
            while (true)
            {
                try
                {
                    MessageHandler();
                }
                catch (Exception ex)
                {
                    StaticComponent.LogEx(ex);
                    break;
                    // Console.WriteLine(ex);
                }
            }

            StaticComponent.LogStr("Exit");
        }

        private void MessageHandler()
        {
            if (ns.CanRead)
            {
                int lengthH = ns.ReadByte();
                int lengthL = ns.ReadByte();

                byte[] write = ReadFromStream(ns, lengthH * 256 + lengthL);

                if (write != null)
                {
                    LOGServerWriter.Instance.WriteLine(Encoding.UTF8.GetString(write));
                }
            }
        }

        private byte[] ReadFromStream(NetworkStream ns, int msgLength)
        {
            try
            {
                if (msgLength <= 0)
                {
                    return null;
                }

                int newBytes = 0;
                int receivedBytes = 0;

                while (newBytes != -1 && receivedBytes < msgLength)
                {
                    newBytes = ns.Read(incoming, 0, msgLength);
                    receivedBytes = receivedBytes + newBytes;
                }

                if (receivedBytes != msgLength)
                {
                    Console.WriteLine("Incomplete Packet is sent to the server!");

                    return null;
                }

                byte[] result = new Byte[msgLength];
                Array.Copy(incoming, 0, result, 0, result.Length);

                return result;
            }
            catch (Exception ex)
            {
                StaticComponent.LogEx(ex);
                return null;
            }
        }
    }
}
